/**
 * 
 */
package truerefactor.metrics;

import java.util.List;

import truerefactor.graph.ClassNode;
import truerefactor.graph.CodeGraph;
import truerefactor.graph.CodeNode;

/**
 * DIT - An Implementation of the Depth of Inheritance Tree metric which finds
 * the largest depth with in a codebase
 * 
 * @author Isaac Griffith
 */
public class DIT extends Metric {

    /**
     * Creates a new Instance of the DIT metric
     */
    public DIT()
    {
        this.shortName = "DIT";
        this.name = "Depth of the Inheritance Tree";
        this.description = "";
    }

    /*
     * (non-Javadoc)
     * @see truerefactor.metrics.Metric#measure(truerefactor.graph.CodeGraph)
     */
    @Override
    public double measure(CodeGraph graph)
    {
        int best = 0;
        List<ClassNode> sources = graph.getClasses();
        for (CodeNode source : sources)
        {
            int temp = 0;

            temp = measure(source);

            if (temp > best)
            {
                best = temp;
            }
        }

        return best;
    }

    /**
     * A recursive function that returns the deepest depth of any class within a
     * given list of ClassNodes
     * 
     * @param depth
     *            previous depth found
     * @param nodes
     *            list of class nodes to still be processed
     * @return deepest depth yet found
     */
    private static int getDepth(int depth, List<ClassNode> nodes)
    {
        int bestDepth = depth;
        if (nodes.isEmpty())
        {
            return depth;
        }
        else
        {
            for (ClassNode node : nodes)
            {
                int tempDepth = 0;
                if (node instanceof ClassNode)
                {
                    ClassNode cNode = (ClassNode) node;
                    tempDepth = getDepth(depth + 1, cNode.getParentClasses());

                    if (tempDepth > bestDepth)
                    {
                        bestDepth = tempDepth;
                    }
                }
            }

            return bestDepth;
        }
    }

    /**
     * For a provided classNode, this method calls the getDepth method on all of
     * the provided classes subclasses until no subclasses are found.
     * 
     * @param source
     *            root of an inheritance tree in which DIT measurement is
     *            required
     * @return the deepest depth for the given root class node
     */
    public static int measure(CodeNode source)
    {
        int temp = 0;

        if (source instanceof ClassNode)
        {
            ClassNode cSource = (ClassNode) source;

            temp = getDepth(1, cSource.getSubClasses());
        }

        return temp;
    }
}
